/**
 * Intervals.java
 *
 * Created on Feb 27, 2006 at 3:07:59 PM
 *
 * Copyright 2008 the Desert Labs Project (http://desertlabs.us)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package us.desertlabs.number;

import java.util.SortedSet;
import java.util.TreeSet;

/**
 * This is a storage class for instances of <CODE>Interval</CODE>. It
 * guarantees that any time the full set of <CODE>Intervals</CODE> is
 * requested, the set provided will be the minimum possible.
 *
 * @author Brandon Franklin
 */
public class Intervals {

    /** The actual list of intervals */
    final private SortedSet<Interval> intervals;

    /** Whether or not the list has been optimized since the last addition */
    private boolean optimized;

    /**
     * Constructs a new instance of <CODE>Intervals</CODE>.
     */
    public Intervals() {
        intervals = new TreeSet<Interval>();
        optimized = true;
    }

    /**
     * Adds a new <CODE>Interval</CODE> to the collection of them.
     *
     * @param interval the new <CODE>Interval</CODE> to add
     */
    public void addInterval( final Interval interval ) {
        intervals.add( interval );
        optimized = false;
    }

    /**
     * Returns an array of the <CODE>Interval</CODE>s that compose this
     * collection. Before returning, this method collapses the set of objects to
     * the minimum possible.
     *
     * @return an array of the <CODE>Interval</CODE>s that compose this
     *         collection
     */
    public Interval[] getIntervals() {

        if( !optimized ) {
            Interval currentInterval = intervals.last();
            SortedSet<Interval> headSet = intervals.headSet( currentInterval );

            while( (headSet != null) && (!headSet.isEmpty()) ) {
                final Interval otherInt = headSet.last();
                if( currentInterval.canMergeWith( otherInt ) ) {
                    intervals.remove( currentInterval );
                    intervals.remove( otherInt );
                    intervals.add( currentInterval.merge( otherInt ) );

                    currentInterval = intervals.last();
                } else {
                    currentInterval = otherInt;
                }

                headSet = intervals.headSet( currentInterval );
            }

            optimized = true;
        }

        return intervals.toArray( new Interval[intervals.size()] );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        for( final Interval interval : getIntervals() ) {
            sb.append( interval.toString() );
        }

        return sb.toString();
    }
}
